package service

import (
	"encoding/json"
	"strconv"
	"time"
	"web_framework/config"
	"web_framework/model"
	"web_framework/pkg/constvar"
	. "web_framework/pkg/e"
	"web_framework/pkg/errno"
	"web_framework/service/lianle"
	"web_framework/storage"
)

func GetUserInfo(uid int, sn string, t int) ( info model.UserInfo, err error) {

	// 共享模式 获取
	shareModelStr := "1"
	speedKey := constvar.RouterRedisPrefix + sn + constvar.RedisRouterLimitSpeed
	bo, err := storage.RedisHExists(speedKey, "upspeed")
	if err == nil && bo {
		speed, _ := storage.RedisHGet(speedKey, "upspeed")
		if speed != "" {
			speedNum, _ := strconv.Atoi(speed)
			if speedNum == 0 {
				shareModelStr = "0"
			}
		}
	}

	// 是否需要强制刷新缓存数据
	userInfoKey := constvar.RedisUserInfo + strconv.Itoa(uid)
	if t <= 0 {
		storage.RedisExpire(userInfoKey, 0)
	}

	// 先Redis 再DB
	if storage.RedisExists(userInfoKey) {
		byteList, err := storage.RedisGetList(userInfoKey)
		if err != nil {
			Log("Info", "取redis失败", err.Error())
			return info, err
		}
		// 取值转换
		err = json.Unmarshal(byteList, &info)
		info.ShareModel, _ = strconv.Atoi(shareModelStr)
		return info, err
	}

	info, err = storage.GetUserInfoRelation(config.C.DB.DB, uid)
	if err != nil {
		Log("Info", "取DB数据失败", err.Error())
		return
	}
	info.UserPic = GetPicPath(info.UserPic)
	info.TotalShareSize = SizeFormat(info.TotalSize.Int64)

	// 先Redis 再DB
	var groupName, routeVersion, routerName string
	groupKey := constvar.RedisGroupInfo + strconv.Itoa(info.GroupID)
	if storage.RedisExists(groupKey) {
		re, _ := storage.RedisZRange(groupKey,0, 0)
		groupName = re[0]
	}else {
		groupInfo, _ := storage.GetGroupInfo(config.C.DB.DB, info.GroupID)
		groupName = groupInfo.GroupName
		storage.RedisZAdd(groupKey, groupName, time.Now().Unix())
	}
	info.GroupName = groupName

	// 路由器基本信息
	routeVersion, err = lianle.GetVersion(sn)
	if err != nil {
		Log("Info", "调用盛天接口失败", err.Error())
		return info, err
	}

	// 路由器名称
	if sn == "" {
		return info, nil
	}
	routerName = GetRouterName(sn)

	//TODO 有SN码可以获取路由器相关信息
	baseRouterInfoKey := constvar.RouterRedisPrefix + sn + constvar.RedisRouterInfo
	if storage.RedisExists(baseRouterInfoKey) {
		routeVersion, _ = storage.RedisHGet(baseRouterInfoKey, "route_version")
		shareModelStr, _ = storage.RedisHGet(baseRouterInfoKey, "share_model")
		routerName, _ = storage.RedisHGet(baseRouterInfoKey, "name")
	}
	mapData := make(map[string]interface{}, 3)
	mapData["route_version"] = routeVersion
	mapData["share_model"] = shareModelStr
	mapData["name"] = routerName
	storage.RedisHSet(baseRouterInfoKey, mapData, -1)
	info.RouteVersion = routeVersion
	info.ShareModel, _ = strconv.Atoi(shareModelStr)
	info.RouterName = routerName
	redisInfo, _ := json.Marshal(info)
	bo, err = storage.RedisSet(userInfoKey, redisInfo, constvar.RedisExpireDay)
	if bo {
		Log("Info", "设置Redis失败")
		return info, nil
	}
	return info, err
}

// 校验用户token
func CheckUserToken(uid int, token string) (error, bool) {

	if uid < 1 {
		Log("Info", errno.ParamsEmpty.Info)
		return errno.ParamsEmpty, false
	}

	tokenKey := constvar.RedisUserToken + strconv.Itoa(uid)
	bo, err := storage.RedisZIsMember(tokenKey, token)
	if err == nil && bo {
		return nil, true
	}

	// Redis找不到去搜索DB
	find, err := storage.GetUserTokenByUidAndToken(config.C.DB.DB, uid, token)
	if find > 0 {
		Log("Info", "取DB数据失败")
		return nil, true
	}

	return errno.ErrDatabase, false
}

// 用户token相关
func AddUserToken(uid, client int, registerRationId string) (err error, token string) {

	if uid < 1 {
		errno.ParamsEmpty.Info += "{ uid }"
		Log("Info", errno.ParamsEmpty.Info)
		return errno.ParamsEmpty, ""
	}

	// 随机生成Token
	token = Md5Str(strconv.FormatInt(MicroTime(), 10) + strconv.Itoa(RandInt(1000, 9999)))

	var userToken model.UserToken
	userToken.Uid = uid
	userToken.Client = client
	userToken.Token = token
	userToken.RegisterRationId = registerRationId

	err = storage.AddUserToken(config.C.DB.DB, &userToken)
	if err != nil {
		Log("Info", "写入token失败", err.Error())
		return err, ""
	}

	// 写入redis
	tokenKey := constvar.RedisUserToken + strconv.Itoa(uid)
	storage.RedisZAdd(tokenKey, token, time.Now().Unix())

	// 检测是否已经用户满了10个token
	count, err := storage.GetUserTokenCount(config.C.DB.DB, uid)
	if err != nil {
		Log("Info", "Token 已经超过10个", err.Error())
		return err, ""
	}

	// 删掉库和redis 里面多的token
	if count > constvar.UserTokenLimit {
		deleteToken, err := storage.GetUserToken(config.C.DB.DB, uid)
		if err != nil {
			Log("Info", "获取DB中的Token失败", err.Error())
			return err, ""
		} else {
			err = storage.DeleteUserToken(config.C.DB.DB, uid, 1)
			if err != nil {
				Log("Info", "删除Token失败", err.Error())
				return err, ""
			}
		}
		checkToken, _ := storage.RedisZRange(tokenKey, 0, 0)
		if len(checkToken) > 0 && checkToken[0] == deleteToken {
			_, err := storage.RedisZRem(tokenKey, deleteToken)
			if err != nil {
				Log("Info", "Token 写库失败", err.Error())
				return err, ""
			}
		}
	}

	return nil, token
}

func UserRegisterInit(uid int, ip int64) error {

	// 注册完成后的数据初始化  默认初始化失败不处理
	db := config.C.DB.DB
	// 初始化user_amount
	storage.RegisterInitUserAmount(db, uid)

	// 初始化count
	storage.RegisterInitCount(db, uid)

	// 初始化user_status
	storage.RegisterInitUserStatus(db, uid, ip)

	// 初始化 user_extend
	storage.RegisterInitUserExtend(db, uid)

	return nil
}

//根据sn获取绑定用户的所有token
func GetUserTokenBySn(sn string)([]string ,error){
	//查询绑定路由器的uid
	deviceBindInfo, err := storage.GetDeviceBindBySn(config.C.DB.DB, sn)
	if err != nil {
		Log("Info", "获取DB中路由器信息失败", err.Error())
		return nil ,err
	}

	//查询uid下的所有有效token
	tokenKey := constvar.RedisUserToken + strconv.FormatInt(deviceBindInfo.UID.Int64, 10)
	tokenSilce, getZErr:= storage.RedisZRange(tokenKey, 0, 10)
	if getZErr != nil {
		Log("Info", "获取Redis中路由器信息失败", getZErr.Error())
		return nil ,getZErr
	}

	return tokenSilce,nil
}